<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace Hyperf\ViewEngine;

use Countable;
use Hyperf\Collection\Arr;
use Hyperf\Contract\MessageBag;
use Stringable;

class ViewErrorBag implements Countable, Stringable
{
    /**
     * The array of the view error bags.
     */
    protected array $bags = [];

    /**
     * Dynamically call methods on the default bag.
     *
     * @param string $method
     * @param array $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->getBag('default')->{$method}(...$parameters);
    }

    /**
     * Dynamically access a view error bag.
     *
     * @param string $key
     * @return MessageBag
     */
    public function __get($key)
    {
        return $this->getBag($key);
    }

    /**
     * Dynamically set a view error bag.
     *
     * @param string $key
     * @param MessageBag $value
     */
    public function __set($key, $value)
    {
        $this->put($key, $value);
    }

    /**
     * Convert the default bag to its string representation.
     */
    public function __toString(): string
    {
        return (string) $this->getBag('default');
    }

    /**
     * Checks if a named MessageBag exists in the bags.
     *
     * @param string $key
     * @return bool
     */
    public function hasBag($key = 'default')
    {
        return isset($this->bags[$key]);
    }

    /**
     * Get a MessageBag instance from the bags.
     *
     * @param string $key
     * @return \Hyperf\Support\MessageBag
     */
    public function getBag($key)
    {
        return Arr::get($this->bags, $key) ?: new \Hyperf\Support\MessageBag();
    }

    /**
     * Get all the bags.
     *
     * @return array
     */
    public function getBags()
    {
        return $this->bags;
    }

    /**
     * Add a new MessageBag instance to the bags.
     *
     * @param string $key
     * @return $this
     */
    public function put($key, MessageBag $bag)
    {
        $this->bags[$key] = $bag;

        return $this;
    }

    /**
     * Determine if the default message bag has any messages.
     *
     * @return bool
     */
    public function any()
    {
        return $this->count() > 0;
    }

    /**
     * Get the number of messages in the default bag.
     */
    public function count(): int
    {
        return $this->getBag('default')->count();
    }
}
